﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SZJT.Framework.Adapter
{
    /// <summary>
    /// GetUserID
    /// </summary>
    public static class LoginTicket
    {
        public static string CreateAccountXml(string taskGuid, string userName,string userPwd,string encryptTime,bool isSocket=false)
        {
            var ip = GetHostIp();
            var sb=new StringBuilder();
            sb.Append(string.Format("<Document TaskGuid=\"{0}\" DataGuid=\"\" DataType=\"LoginTicket\">",taskGuid));
            sb.Append("<UserNameTicket>");
            sb.Append(string.Format("<UserName Type=\"TEXT\">{0}</UserName>",userName));
            sb.Append(string.Format("<Password Type=\"TEXT\">{0}</Password>",userPwd));
            sb.Append(string.Format("<EncryptTime Type=\"TEXT\">{0}</EncryptTime>", encryptTime));
            sb.Append("</UserNameTicket>");
            sb.Append(string.Format("<IPAddress Type=\"TEXT\">{0}</IPAddress>",ip));
            sb.Append("</Document>");
            LoggerHelper.WriteCodePointInfo("cert ip:" + ip);
            return sb.ToString();
        }

        public static string CreateCertXml(string taskGuid, string userName,string encryptTime,bool isSocket=false)
        {
            var ip = GetHostIp();
            var sb = new StringBuilder();
            sb.Append(string.Format("<Document TaskGuid=\"{0}\" DataGuid=\"\" DataType=\"CertTicket\">", taskGuid));
            sb.Append("<UserNameTicket>");
            sb.Append(string.Format("<UserName Type=\"TEXT\">{0}</UserName>", userName));
            sb.Append(string.Format("<EncryptTime Type=\"TEXT\">{0}</EncryptTime>", encryptTime));
            sb.Append("</UserNameTicket>");
            sb.Append(string.Format("<IPAddress Type=\"TEXT\">{0}</IPAddress>", ip));
            sb.Append("</Document>");
            LoggerHelper.WriteCodePointInfo("cert ip:" + ip);
            return sb.ToString();
        }

        public static string EncryptByPublicKey(string xmlPublicKey, string cleanString)
        {
            var byteConverter = new UTF8Encoding();
            var dataToEncrypt = byteConverter.GetBytes(cleanString);
            var RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(xmlPublicKey);
            var encryptData = RSA.Encrypt(dataToEncrypt, false);
            var encryptString = Convert.ToBase64String(encryptData);
            return encryptString;
        }
        /// <summary>
        /// 获取本地证书
        /// </summary>
        /// <param name="certName">证书名称</param>
        /// <param name="certType">证书类型</param>
        /// <param name="storeName">存储名称</param>
        /// <param name="storeLocation">存储位置</param>
        /// <returns></returns>
        internal static X509Certificate2 GetLocalCert(string certName, string certType, string storeName, string storeLocation)
        {
            var CN = certName;
            var CT = string.IsNullOrEmpty(certType) ? "X509Certificate2" : certType;
            var SN = string.IsNullOrEmpty(storeName) ? "My" : storeName;
            var SL = string.IsNullOrEmpty(storeLocation) ? "LocalMachine" : storeLocation;
            var storeLocal = SL.ToLower().Equals("currentuser") ? StoreLocation.CurrentUser : StoreLocation.LocalMachine;
            var store = new X509Store(SN, storeLocal);
            try
            {
                store.Open(OpenFlags.MaxAllowed);
                foreach (var x509 in store.Certificates)
                {
                    if (!x509.Subject.Contains(CN)) continue;
                    return x509;
                }
            }
            catch (Exception er) { throw new Exception("查询证书时发生错误", er); }
            finally
            {
                store.Close();
            }
            return null;
        }
        /// <summary>
        /// 根据私钥解密
        /// </summary>
        /// <param name="cert">本地证书</param>
        /// <param name="encryptString">加密字符串</param>
        /// <returns>字符串</returns>
        internal static string DecryptByPrivateKey(X509Certificate2 cert, string encryptString)
        {
            var decrypt = (RSACryptoServiceProvider)cert.PrivateKey;
            var decryptData = Convert.FromBase64String(encryptString);
            var dataToDecrypt = decrypt.Decrypt(decryptData, false);
            var byteConverter = new UTF8Encoding();
            return byteConverter.GetString(dataToDecrypt);
        }
        /// <summary>
        /// 根据口令解密UserId
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Decode(string str, string key)
        {
            var provider = new DESCryptoServiceProvider
            {
                Key = Encoding.ASCII.GetBytes(key.Substring(0, 8)),
                IV = Encoding.ASCII.GetBytes(key.Substring(0, 8))
            };
            var buffer = new byte[str.Length / 2];
            for (var i = 0; i < (str.Length / 2); i++)
            {
                var num2 = Convert.ToInt32(str.Substring(i * 2, 2), 0x10);
                buffer[i] = (byte)num2;
            }
            var stream = new MemoryStream();
            var stream2 = new CryptoStream(stream, provider.CreateDecryptor(), CryptoStreamMode.Write);
            stream2.Write(buffer, 0, buffer.Length);
            stream2.FlushFinalBlock();
            stream.Close();
            return Encoding.GetEncoding("UTF-8").GetString(stream.ToArray());
        }
        /// <summary>
        /// 获取解密口令密钥
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetKeyStr(string key)
        {
            var length = key.Length;
            var flag = 8 - length;
            var result = key;
            if (length > 8)
                return key.Substring(0, 8);
            while (flag > 0)
            {
                result += "*";
                flag--;
            }
            return result;
        }

        public static string GetIP()
        {
            string strIP = "";
            if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
                strIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
            else
                strIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
            return strIP;
        }

        public static string GetHostIp()
        {
            var ipe = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in ipe.AddressList.Where(ip => ip.ToString().IndexOf(':') == -1))
            {
                return ip.ToString();
            }
            return string.Empty;
           // IPAddress ipa = ipe.AddressList[0];
           // return ipa.ToString();
        }

        internal static string ExtractIp(string address)
        {
            if (!string.IsNullOrEmpty(address))
            {
                int index = address.LastIndexOf(":");
                return address.Substring(0, index);
            }
            else
                return "";
        }

        internal static string ExtractPort(string address)
        {
            if (!string.IsNullOrEmpty(address))
            {
                int index = address.LastIndexOf(":");
                return address.Substring(index + 1);
            }
            else
                return "";
        }
    }
}
